package com.ruoyi.demo.service;

import com.ruoyi.demo.util.MinIOUtil;
import com.ruoyi.system.domain.Agenda;
import com.ruoyi.system.domain.Meet;
import com.ruoyi.system.domain.MeetMaterials;
import com.ruoyi.system.mapper.AgendaMapper;
import com.ruoyi.system.mapper.MeetMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;

/**
 * @author 33692
 */
@Service
@Slf4j
//@RestController
public class VideoProcessingService {

    @Autowired
    private AgendaMapper agendaMapper;

    @Autowired
    private MeetMapper meetMapper;


    @Autowired
    private MinIOUtil minIOUtil;

    private static final String FFMPEG_PATH = "D:/ffmpeg/ffmpeg7.0/bin/ffmpeg.exe";

    public void splitVideoByAgenda(MeetMaterials meetMaterials,String videoPath,String audioPath) {

        //获取该会议的起始时间
        Meet meet = meetMapper.selectMeetByMeetId(Math.toIntExact(meetMaterials.getMeetId()));
        List<Agenda> agendaList = agendaMapper.selectAgendaByMeetId(meetMaterials.getMeetId());
        // 创建一个列表来存储所有生成的文件路径
        List<String> filePathsToDelete = new ArrayList<>();

// 假设 agendaList 和 meet 已经定义并初始化
        boolean hasSignInAgenda = false;
        Date signInEndTime = null;

// 遍历 agendaList 查找 "会议签到" 议程
        for (Agenda item : agendaList) {
            if ("会议签到".equals(item.getAgendaTitle())) {
                hasSignInAgenda = true;
                signInEndTime = item.getEndTime(); // 获取签到议程的结束时间
                break;  // 找到签到议程后就可以停止遍历
            }
        }

        for (Agenda item : agendaList) {
            if ("会议签到".equals(item.getAgendaTitle())) {
                continue;
            }
            String agendaId = String.valueOf(item.getAgendaId());
            Date startTime = item.getStartTime();
            Date endTime = item.getEndTime();
            String agendaTitle = item.getAgendaTitle();   // 议程标题

            // 计算视频切割时的时间，转换为秒数（例如：00:01:30 转为 90秒）
            long startSeconds;
            long durationSeconds = convertToSeconds(endTime) - convertToSeconds(startTime);

            if (hasSignInAgenda) {
                // 如果有签到议程，开始时间是其他议程的开始时间减去签到结束时间
                startSeconds = convertToSeconds(startTime) - convertToSeconds(signInEndTime);
            } else {
                // 如果没有签到议程，开始时间是其他议程的开始时间减去会议的开始时间
                startSeconds = convertToSeconds(startTime) - convertToSeconds(meet.getStartTime());
            }


//            // 计算视频切割时的时间，转换为秒数（例如：00:01:30 转为 90秒）
//            long startSeconds = convertToSeconds(startTime) - convertToSeconds(meet.getStartTime());
//            long durationSeconds = convertToSeconds(endTime) - convertToSeconds(startTime);


            // 输出路径，命名规则为：原视频文件名_议程标题.mp4
            String videoOutputPath = videoPath.replace(".mp4", "_" + agendaId + "_" + agendaTitle + ".mp4");
//            String command = String.format("ffmpeg -i %s -ss %d -t %d -c copy %s",
//                    videoPath, startSeconds, durationSeconds, videoOutputPath);
//            String command = String.format("ffmpeg -i %s -ss %d -t %d -c:v libx264 -c:a libmp3lame %s",
//                    videoPath, startSeconds, durationSeconds, videoOutputPath);
            String command = String.format("%s -i %s -ss %d -t %d -c:v libx264 -c:a libmp3lame %s",
                   FFMPEG_PATH, videoPath, startSeconds, durationSeconds, videoOutputPath);

            log.info("command :{}",command);
            executeCommand(command);
            log.info("commend ok !!!!");
            MultipartFile multipartFile = minIOUtil.getLocalMultipartFile(videoOutputPath);
            String videoUrl = minIOUtil.uploadAgendaVideo(multipartFile, String.valueOf(meetMaterials.getMeetId()));
            log.info("拆分视频: {}", videoOutputPath);


            // 输出路径，命名规则为：原音频文件名_议程标题.mp3
            String audioOutputPath = audioPath.replace(".mp3", "_" + agendaId + "_"+ agendaTitle + ".mp3");
            // FFmpeg命令：根据议程的开始时间和时长进行音频切割
//            String audioCommand = String.format("ffmpeg -i %s -ss %d -t %d -c copy %s",
//                    audioPath, startSeconds, durationSeconds, audioOutputPath);

//            String audioCommand = String.format(
//                    "ffmpeg -i %s -ss %d -t %d -c:a libmp3lame %s",
//                    audioPath, startSeconds, durationSeconds, audioOutputPath);
            String audioCommand = String.format(
                    "%s -i %s -ss %d -t %d -c:a libmp3lame %s",
                    FFMPEG_PATH, audioPath, startSeconds, durationSeconds, audioOutputPath);
            log.info("audioCommand :{}",audioCommand);
            // 执行FFmpeg命令进行音频切割
            executeCommand(audioCommand);
            MultipartFile multipartFile2 = minIOUtil.getLocalMultipartFile(audioOutputPath);
            // 使用uploadAgendaVideo方法上传视频
            String audioUrl = minIOUtil.uploadAgendaAudio(multipartFile2, String.valueOf(meetMaterials.getMeetId()));
            log.info("拆分音频成功，路径：{}", audioOutputPath);


            // 将路径添加到列表中
            filePathsToDelete.add(videoOutputPath);
            filePathsToDelete.add(audioOutputPath);


            // 保存拆分后的视频路径到数据库
            item.setVideoPath(videoUrl);
            item.setVoicePath(audioUrl);
            agendaMapper.updateAgenda(item);
        }
        // 等待 10 秒钟，确保文件不再被占用
        try {
            Thread.sleep(10000);  // 等待 10 秒
        } catch (InterruptedException e) {
            log.error("等待文件操作完成时发生中断异常", e);
        }
//         循环结束后，统一删除文件
        deleteFiles(filePathsToDelete);
    }

    /**
     * 删除文件列表中的所有文件
     */
    private void deleteFiles(List<String> filePaths) {
        for (String filePath : filePaths) {
            try {
                Path path = Paths.get(filePath);
                if (Files.exists(path)) {
                    Files.delete(path);
                    log.info("文件删除成功: {}", filePath);
                } else {
                    log.warn("文件不存在，无法删除: {}", filePath);
                }
            } catch (IOException e) {
                log.error("删除文件失败: {}", filePath, e);
            }
        }
    }

//    private void executeCommand(String command) {
//        try {
//            Process process = Runtime.getRuntime().exec(command);
//            process.waitFor();  // 等待进程结束
//        } catch (Exception e) {
//            log.error("执行命令失败", e);
//        }
//    }
    private void executeCommand(String command) {
        try {
            // 执行 FFmpeg 命令
            Process process = Runtime.getRuntime().exec(command);

            // 异步读取进程输出流（stdout）
            new Thread(() -> {
                try {
                    InputStream inputStream = process.getInputStream();
                    BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
                    String line;
                    while ((line = reader.readLine()) != null) {
                        log.info("FFmpeg stdout: {}", line);
                    }
                } catch (IOException e) {
                    log.error("读取 stdout 错误", e);
                }
            }).start();

            // 异步读取错误流（stderr）
            new Thread(() -> {
                try {
                    InputStream errorStream = process.getErrorStream();
                    BufferedReader reader = new BufferedReader(new InputStreamReader(errorStream));
                    String line;
                    while ((line = reader.readLine()) != null) {
                        log.error("FFmpeg stderr: {}", line);
                    }
                } catch (IOException e) {
                    log.error("读取 stderr 错误", e);
                }
            }).start();

            // 等待进程结束
            int exitCode = process.waitFor();
            if (exitCode == 0) {
                log.info("FFmpeg 进程正常结束");
            } else {
                log.error("FFmpeg 进程异常结束，退出码: {}", exitCode);
            }
        } catch (Exception e) {
            log.error("执行命令失败", e);
        }
    }

    /**
     * 将时间转换为秒数（例如：00:01:30 -> 90秒）
     */
    private long convertToSeconds(Date time) {
        long milliseconds = time.getTime();
        return milliseconds / 1000;  // 转换为秒
    }
}
